package JNumberField;

import java.awt.event.KeyEvent;
import javax.swing.JTextField;

/**
 * This field will only allow presses from number 0 to 9
 * as well as the minus character. No exceptions are thrown in
 * this class, though the getNumber() method might trigger a 
 * NumberFormatException if for some reason the program does not
 * work as intended.
 * 
 * @author Mads FS. (Mads Sønderstrup)
 * @version 1
 * @see NumberFormatException
 */

public class JIntField extends JTextField {
    private String badchars = "`~!@#$%^&*()_+=\\|\"':;?/>.<,¤½§";
    private char fieldType = '0';
    
    /**
     * Constructs an empty field without any parameters
     */
    public JIntField() {
    
    }
    
    /**
     * Constructs a field with the specified integer
     * @param i Integer to start with.
     */
    public JIntField(int i) {
        setText("" + i);
    }
    
    /**
     * Constructs a field as the specified type. The default type is neutral.
     * @param fieldType <pre>0: Neutral field. Takes both positive and negative numbers. (Default)</pre>
     *                  <pre>-: Minus field. Takes only negative numbers.</pre>
     *                  <pre>+: Plus field. Takes only positive numbers.</pre>
     */
    public JIntField(char fieldType) {
        this.fieldType = fieldType;
        if(fieldType == '-') {
            setText("-");
        }
    }
    
    /**
     * Set the number of the field.
     * @param i Integer to put in the field.
     */
    
    public void setNumber(int i) {
        switch(fieldType) {
            case '+':
                setText(""+i);
                break;
            case '-':
                if(getText().charAt(0) != '-')
                    setText("-"+i);
                else
                    setText(getText()+i);
                break;
        }
    }
    
    /**
     * @return the fields current integer.
     */
    
    public int getNumber() {
        String s = getText();
        
        if(s.length() == 1 && s.charAt(0) == '-') {
            setText(s + "0");
            s = getText();
        } else if(s.length() == 0) {
            setText("0");
            s = getText();
        }
        
        // If the user thinks he is smart and removes the minus
        // we will make sure that the minus is still there when
        // we retrirve the number.
        if(fieldType == '-') {
            if(s.charAt(0) == '-' && getText().equals("-0.0")) {
                // Do nothing
            } else if(s.length() > 1) {
                // Do nothing
            }
        }
        return Integer.parseInt(s);
    }
    
    /**
     * Add a special character if it isn't present by default.
     * The library comes with a string, that contains all the special characters
     * available to the author at the time of creation. If the user of this library
     * wishes to add more special characters the user could potentially add which
     * shouldn't be permitted, please use this method.
     * @param c Character to add to the list of characters not allowed to be pressed.
     */
    public void addSpecialChar(char c) {
        if(badchars.indexOf(c) > -1) {
            // Do nothing
        } else {
            badchars += c;
        }
    }
    
    /**
     * Add an array of special characters if they are not present by default.
     * The library comes with a string, that contains all the special characters
     * available to the author at the time of creation. If the user of this library
     * wishes to add more special characters the user could potentially add which
     * shouldn't be permitted, please use this method.
     * @param array Array of special characters to add to the list of characters
     * not allowed to be pressed.
     */
    public void addSpecialCharArray(char[] array) {
        if(array.length == 0) {
            
        } else {
            for(char c : array) {
                if(badchars.indexOf(c) > -1) {
                    // The character is already on the list
                } else {
                    badchars += c;
                }
            }
        }
    }
    
    @Override
    public void processKeyEvent(KeyEvent ev) {
        char c = ev.getKeyChar();
        String s = getText();
        
        //No white space allowed
        if(ev.getKeyCode() == 32) {
            ev.consume();
        }
        //Check if the field is a minus-field only.
        if(fieldType == '-') {
            // It is a minus field.            
            if(s.length() == 0) {
                setText("-");
                return;
            }
            if(s.charAt(0) != '-') {
                // The first character in the field wasn't a minus
                ev.consume();
                setText("-" + s);
            }
        }
        // Is the character a letter, or part of our badchars string
        if(Character.isLetter(c) && !ev.isAltDown() || badchars.indexOf(c) > -1) {
            // It was, so we consume the keypress.
            ev.consume();
            return;
        }
        // Was the minus key pressed, and is the field neutral.
        if(fieldType == '-') {
            // It is a minus field.            
            if(s.length() == 0) {
                setText("-");
                return;
            }
            if(s.charAt(0) != '-') {
                // The first character in the field wasn't a minus
                ev.consume();
                setText("-" + s);
            }
        }
        // Is the character a letter, or part of our badchar string.
        if(Character.isLetter(c) && !ev.isAltDown() || badchars.indexOf(c) > -1) {
            // It was, so we consume the keypress.
            ev.consume();
            return;
        }
        // Was the minus key pressed, and is the field neutral.
        if(c == '-' && fieldType == '0') {
            // The minus have to be the first character.
            if(s.length() == 0) {
                setText("-" + s);
                return;
            }
            if(s.charAt(0) == '-') {
                // There already is a minus, so consume the keypress
                ev.consume();
                // It might not be the fist keypress the user makes.
            } else if(getDocument().getLength() > 0) {
                // Lets place a minus in front of the line.
                ev.consume();
                setText("-" + s);
            } else {
                // Else we just place it.
                super.processKeyEvent(ev);
            }
            // Maybe it's a positive field.
        } else if(c == '-' && fieldType == '+') {
            //It is a positive field, so lets make sure that
            // the minus is ignored.
            ev.consume();
        } else if(c == '-' && fieldType == '-') {
            ev.consume();
        } else {
            // If everything else fails, we just let the character be added.
            super.processKeyEvent(ev);
        }
    }
}